#pragma once
// model: 主要用来和数据进行交互

#include <iostream>
#include <string>
#include <vector>
#include <unordered_map>
#include <cassert>

#include "../comm/Log.hpp"
#include "../comm/util.hpp"

namespace ns_model
{
    using namespace ns_util;
    struct Question
    {
        std::string _qid; // 题目编号
        std::string _title; // 题目
        std::string _difficulty; // 难度
        int _cpu_limit; // 时间限制
        int _mem_limit; // 空间限制
        std::string _desc; // 题目的描述
        std::string _header; // 题目中编辑器里的内容
        std::string _tail; // 测试用例，与_header拼接形成完整代码
    };

    const std::string question_list = "./questions/questions.list";
    const std::string question_path = "./questions/";
    class Model
    {
    public:
        Model()
        {
            assert(LoadQuestionList(question_list));
        }

        // 加载 questions_list
        bool LoadQuestionList(const std::string& question_list)
        {
            std::string content;
            if(!FileUtil::ReadFile("./questions/questions.list", &content, true))
            {
                LOG(FATAL, "加载题库失败, 检查是否存在: ./questions/questions.list 文件\n");
                return false;
            }

            // 拿到全部行
            std::vector<std::string> lines;
            StringUtil::SplitString(content, "\n", &lines);

            for(auto line : lines)
            {
                // 拿到每一行的信息
                std::vector<std::string> ques_info;
                StringUtil::SplitString(line, " ", &ques_info);

                if(ques_info.size() == 5)
                {
                    // 题号 名字 难度 时间 空间
                    Question q;
                    q._qid = ques_info[0];
                    q._title = ques_info[1];
                    q._difficulty = ques_info[2];
                    q._cpu_limit = std::stoi(ques_info[3]);
                    q._mem_limit = std::stoi(ques_info[4]);

                    // 具体题目的题面描述、代码提示、测试用例
                    std::string question_number_path = question_path;
                    question_number_path += "/";
                    question_number_path += ques_info[0];
                    question_number_path += "/";

                    std::string question_number_desc = question_number_path + "desc.txt";
                    std::string question_number_header = question_number_path + "header.cpp";
                    std::string question_number_tail = question_number_path + "tail.cpp";
                    
                    FileUtil::ReadFile(question_number_desc, &q._desc, true);
                    FileUtil::ReadFile(question_number_header, &q._header, true);
                    FileUtil::ReadFile(question_number_tail, &q._tail, true);
                    
                    _questions.insert({q._qid, q});
                }
                else  
                {
                    LOG(ERROR, "加载部分题库失败: %s\n", line.c_str());
                    LOG(INFO, "ques_info.size(): %d\n", ques_info.size());
                    for(auto e : ques_info)
                    {
                        std::cout << e << std::endl;
                    }
                    continue;
                }
            }
            LOG(INFO, "加载题库成功\n");
            return true;
        }

        bool GetAllQuestion(std::vector<Question>* out)
        {
            if(_questions.size() == 0)
            {
                LOG(ERROR, "获取题库失败\n");
                return false;
            }
            
            for(const auto& p : _questions)
            {
                out->push_back(p.second);
            }
            
            return true;
        }

        bool GetOneQuestion(std::string number, Question* q)
        {
            const auto& iter = _questions.find(number);
            if(iter == _questions.end())
            {
                LOG(ERROR, "用户获取单个题目%s 失败", number.c_str());
                return false;
            }

            *q = iter->second;

            return true;
        }

        ~Model()
        {}
    private:
        std::unordered_map<std::string, Question> _questions; // 题目编号与题目的映射
    };
}